package claybird.controller;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import claybird.dao.PersonneDao;
import claybird.dao.ResultDao;
import claybird.dao.ShootDayDao;
import claybird.dao.TeamDao;
import claybird.dom.Person;
import claybird.dom.Result;
import claybird.dom.ShootDay;
import claybird.dom.Team;

@Controller
public class TeamController {
	@Autowired TeamDao teamDao;
	@Autowired PersonneDao personneDao;
	@Autowired ShootDayDao shootDao;
	@Autowired ResultDao resultDao;
	
	
	public ModelAndView getmv(Long idTeam){
		Team tmpTeam  = teamDao.find(idTeam);
		List<Person> listPers = personneDao.getAllPersonne();
		List<Team> teamList = teamDao.getAllTeamForShootDay(tmpTeam.getShootDay());
		for (Team oneTeam: teamList)
		for(Person pers:oneTeam.getListPerson()){
			listPers.remove(pers);
		}
		ModelAndView mv =new ModelAndView("team_managment","team",tmpTeam);
		mv.addObject("listPerson", listPers);
		return mv;
	}
	
	
	@RequestMapping("team/setPoints")
	public ModelAndView setPoints(@RequestParam("idDay") Long idDay,
									@RequestParam("idPerson") Long idPerson,
									@RequestParam("hit") byte hit,
									@RequestParam("total") byte total){
		Person pers = personneDao.find(idPerson);
		ShootDay day = shootDao.find(idDay);
		if (pers!=null && day!=null){
			Result res = resultDao.findExisting(day, pers);
			if (res==null)res = new Result(day,pers);
			res.setNumberOfClayShooted(hit);
			res.setNumberOfClayTotal(total);
			res.setRealValue((float) hit / (float) total*50);
			res.setEvolution(hit*total/50/pers.getLastHandicap().getCurrentHandicap()*2*100);
			res.setPercentNewHandicap((float) ((pers.getLastHandicap().getCurrentHandicap()*0.8)+(hit*total/50/2.5)));
			resultDao.persist(res);
		}

		ModelAndView mv =new ModelAndView("showshoot","ShootDay",day);
		return mv;
	}
	
	@RequestMapping("team/edit")
	public ModelAndView createShootPage(@RequestParam("id") Long id){
		return this.getmv(id);
	}
	
	@RequestMapping("team/delete")
	public ModelAndView deleteTeam(@RequestParam("id") Long id, @RequestParam("idShootDay") Long idShootDay){
		Team tmpTeam  = teamDao.find(id);
		ShootDay sd = shootDao.find(idShootDay);
		if (tmpTeam !=null && sd !=null){
			teamDao.remove(tmpTeam);
		}

		ModelAndView mv =new ModelAndView("showshoot","ShootDay",sd);
		return mv;
	}
	@RequestMapping("team/addshooter")
	public ModelAndView addShooter(@RequestParam("idTeam") Long idTeam, @RequestParam("idShooter") Long idShooter){
		Team tmpTeam  = teamDao.find(idTeam);
		Person pers = personneDao.find(idShooter);
		if (tmpTeam !=null && pers !=null){
			if(!tmpTeam.getListPerson().contains(pers)){
				tmpTeam.getListPerson().add(pers);
			}
			teamDao.persist(tmpTeam);
		}
		return this.getmv(idTeam);
	}
	@RequestMapping("team/deleteshooter")
	public ModelAndView deleteShooter(@RequestParam("idTeam") Long idTeam, @RequestParam("idShooter") Long idShooter){
		Team tmpTeam  = teamDao.find(idTeam);
		Person pers = personneDao.find(idShooter);
		if (tmpTeam !=null && pers !=null){
			tmpTeam.getListPerson().remove(pers);
			teamDao.persist(tmpTeam);
		}
		return this.getmv(idTeam);
	}
	@RequestMapping("team/generate")
	public ModelAndView generate(@RequestParam("idShoot")Long idShootDay, @RequestParam("number")int numberOfTeam, 
								@RequestParam("idShooter")List<Long> idList){
		ShootDay day = shootDao.find(idShootDay);
		if(numberOfTeam>0 && idList.size()>0){
			List<Team> teamsList = this.generateTeamName(numberOfTeam,day);
			List<Person> shooterList = personneDao.getListByIds(idList);
			List<Person> sortedList = this.sortListShooter(shooterList);
			this.populateTeams(teamsList,sortedList);
			this.saveTeams(teamsList);
		}

		ModelAndView mv =new ModelAndView("showshoot","ShootDay",day);
		return mv;
	}


	private void saveTeams(List<Team> teamsList) {
		for(Team tm : teamsList){
			teamDao.persist(tm);
		}
		
	}


	private List<Person> sortListShooter(List<Person> shooterList) {
		List<Person> sortedList = new ArrayList<Person>();
		sortedList.add(0, shooterList.get(0));
		boolean inserted = false;
		for (int i = 1; i < shooterList.size(); i++) {
			inserted = false;
			for  (int j = 0; j < sortedList.size(); j++){
				if(shooterList.get(i).getLastHandicap().getCurrentHandicap()>
					sortedList.get(j).getLastHandicap().getCurrentHandicap()){
						sortedList.add(j, shooterList.get(i));
						inserted = true;
						break;
				}
			}
			if (!inserted){
				sortedList.add(shooterList.get(i));
			}
			
		}
		for (Person pers:sortedList){
			System.out.println(pers.getForName()+" "+pers.getName()+" "+pers.getLastHandicap().getCurrentHandicap());
		}
		return sortedList;
	}

	private void populateTeams(List<Team> teamsList, List<Person> shooterList) {
		int totalTeams = teamsList.size();
		int numberOfShooter = shooterList.size();
		int iteration = numberOfShooter/totalTeams;
		int reste = numberOfShooter % totalTeams;
		/*On va faire autant de tour que de personne par equipe, 
		 * (on ajoutera les personnes non attribuees si un tour non complet reste a produire)*/
		for (int i = 1;i<=iteration;i++){
			for (int j = 0;j<totalTeams;j++){
				/*si pair on ajoute plus petite equipe si impair, plus grande, 
				 * ainsi reste les plus petites a la fin =>moins inegal*/
				Person shooter;
				if (i%2 ==1){
					shooter = shooterList.get(0);
				}else{
					shooter = shooterList.get(shooterList.size()-1);
				}
				teamsList.get(j).addToList(shooter);
				shooterList.remove(shooter);
			}
		}
		for (int i = 1;i<=reste;i++){
			for (int j = 0;j<totalTeams;j++){
				Person shooter = shooterList.get(shooterList.size()-1);
				teamsList.get(j).addToList(shooter);
				shooterList.remove(shooter);
				if (shooterList.size()==0) return;
			}
		}
		
	}


	private List<Team> generateTeamName(int numberOfTeam, ShootDay day) {
		int current=1;
		List<Team> generatedList = new ArrayList<Team>();
		while (current<=numberOfTeam) {
			generatedList.add(new Team("Equipe "+current, day));
			current++;
		}
		return generatedList;
	}
}
